/**
 * @mxmlc -output=bin/assets/modules/fight.swf -external-library-path+=lib/library.swc -debug=false -noplay
 */
package fight
{
	import fight.model.InfoVO;
	import flash.display.Bitmap;
	import flash.display.Sprite;
	import morn.core.components.Clip;
	
	import fight.view.ControlPanel;
	import fight.view.InfoPanel;
	import fight.view.armytype.BaseArmy;
	import fight.view.armytype.Bowman;
	import fight.view.armytype.Infantry;
	import fight.view.armytype.Leader;
	import fight.view.armytype.Sowar;
	
	import org.airmvc.View;
	
	import utils.T;
	
	import vo.GeneralVO;
	
	/**
	 * ...
	 * @author WLDragon 2014-02-28
	 */
	public class FightV extends View
	{
		
		public function FightV()
		{
		}
		
		override public function init():void
		{
			mapData = [];
			map = new Bitmap();
			addChild(map);
			
			armyPanel = new Sprite();
			armyPanel.y = 17;
			addChild(armyPanel);
			
			controlPanel = new ControlPanel();
			controlPanel.visible = false;
			addChild(controlPanel);
			
			infoPanel = new InfoPanel();
			infoPanel.visible = false;
			addChild(infoPanel);
			
			attackEffect = new Bitmap(App.asset.getAsset("png.fight.fire"));
			attackEffect.visible = false;
			addChild(attackEffect);
			
			arrow = new Clip("png.fight.arrow", 2, 2);
			arrow.visible = false;
			addChild(arrow);
			
			config = T.db.getXml(Cnt.XML_ALGORITHM);
			equipXml = T.db.getXml(Cnt.XML_EQUIP);
			
			infoAttackVO = new InfoVO();
			infoDefenseVO = new InfoVO();
		}
		
		override protected function addListeners():void
		{
			receive(FightC.INIT_MAP, initMap);
			receive(FightC.INIT_FORMATION, initFormation);
			receive(FightC.GIVE_ORDER, giveOrder);
			receive(FightC.OPEN_CONTROL_PANEL, openControlPanel);
			receive(FightC.UPDATE_INFO_PANEL, updateInfoPanel);
			receive(FightC.LEADER_ESCAPE_OR_DIE,handleEnd);
		}
		
		private function handleEnd():void 
		{
			isFightOver = true;
			infoPanel.visible = false;
			send(FightC.SHOW_DEFENSE_HEAD,false);
			Msg.instance.show("战斗结束",140,340,12,fightOver);
		}
		
		private function fightOver():void
		{
			var ba:BaseArmy;
			while (armyPanel.numChildren > 0)
			{
				ba = armyPanel.getChildAt(0) as BaseArmy;
				ba.destroy();
				armyPanel.removeChildAt(0);
			}
			Lyr.map.removeChild(this);
			send(FightC.FIGHT_OVER,infoAttackVO,infoDefenseVO);
		}
		
		private function updateInfoPanel(isAttack:Boolean,prop:String,value:int):void 
		{
			if (isAttack)
			{
				infoAttackVO[prop] -= value;
				infoPanel.update(isAttack,infoAttackVO);
			}
			else
			{
				infoDefenseVO[prop] -= value;
				infoPanel.update(isAttack,infoDefenseVO);
			}
		}
		
		private function giveOrder(orders:Array):void 
		{
			for each(var ba:BaseArmy in attackTeam)
			{
				switch (true) 
				{
					case ba is Leader:
						ba.state = orders[0];
					break;
					case ba is Infantry:
						ba.state = orders[3];
					break;
					case ba is Bowman:
						ba.state = orders[2];
					break;
					case ba is Sowar:
						ba.state = orders[1];
					break;
				}
			}
			
			openInfoPanel();
		}
		
		private function initFormation(type:int, attack:GeneralVO, defense:GeneralVO):void
		{
			isFightOver = false;
			var ba:BaseArmy;
			var i:int = 0;
			var fs1:Array = FORMATIONS[type - 1];
			var fs2:Array = FORMATIONS[Math.random() * 4 >> 0];
			attackTeam = getTeam(true, attack, 0);
			defenseTeam = getTeam(false, defense, 2);
			
			for (i = 0; i < 9; i++)
			{
				mapData[i] = [];
			}
			var infantryType:Array = [];
			var bowmanType:Array = [];
			var sowarType:Array = [];
			var leadType:Array = [];
			
			//摆阵
			for (i = 0; i < attackTeam.length; i++)
			{
				placeArmy(attackTeam[i], fs1, i, true);
				
			}
			for (i = 0; i < defenseTeam.length; i++)
			{
				placeArmy(defenseTeam[i], fs2, i, false);
			}
			
			function placeArmy(b:BaseArmy, formations:Array, index:int, isAttack:Boolean):void
			{
				var tx:int;
				var ty:int;
				if (isAttack)
					tx = formations[index][0];
				else
					tx = 15 - formations[index][0];
				
				ty = formations[index][1];
				b.x = tx * 32;
				b.y = ty * 32;
				mapData[ty][tx] = b;
				armyPanel.addChild(b);
				classify(b);
			}
			
			//分类
			function classify(ba:BaseArmy):void
			{
				switch (true)
				{
					case ba is Leader:
						leadType.push(ba);
					break;
					case ba is Infantry: 
						infantryType.push(ba);
						break;
					case ba is Bowman: 
						bowmanType.push(ba);
						break;
					case ba is Sowar: 
						sowarType.push(ba);
						break;
				}
			}
			//leadType.push(attackTeam[0]);
			//leadType.push(defenseTeam[0]);
			
			allUnit = infantryType.concat(bowmanType, sowarType, leadType);
			curUnitIndex = 0;
			
			initInfo(attackTeam,infoAttackVO);
			initInfo(defenseTeam, infoDefenseVO);
			infoPanel.update(true,infoAttackVO);
			infoPanel.update(false,infoDefenseVO);
			
			controlPanel.update(attack);
			send(FightC.FORMAT_COMPLETE);
			openControlPanel();
		}
		
		private function initInfo(team:Array,infoVo:InfoVO):void
		{
			var isum:int = 0;
			var bsum:int = 0;
			var ssum:int = 0;
			for each(var ba:BaseArmy in team)
			{
				switch (true)
				{
					case ba is Leader:
						//因为Leader继承Sowar，所以判断要放在Sowar之前
						infoVo.strength = ba.hp;
						break;
					case ba is Sowar: 
						ssum += ba.hp;
						break;
					case ba is Bowman: 
						bsum += ba.hp;
						break;
					case ba is Infantry: 
						isum += ba.hp;
						break;
				}
			}
			infoVo.sowarNum = ssum;
			infoVo.bowmanNum = bsum;
			infoVo.infantryNum = isum;
		}
		
		/**
		 * 获取编队
		 */
		private function getTeam(isAttack:Boolean, g:GeneralVO, dir:int):Array
		{
			var skin:String;
			var arr:Array = [];
			var x:XML = (config.team.level.(@id == g.level)[0]).item.(@min <= g.power && g.power <= @max)[0];
			var inum:int = x.@infantry;
			var bnum:int = x.@bowman;
			var snum:int = x.@sowar;
			var n:int = Math.ceil(g.soliders * 0.01);
			var m:int = g.soliders / n >> 0;
			var d:int = g.soliders % n;
			
			var fA:int = getFactorA(g);
			//添加主将
			skin = dir == 0 ? "png.fight.wl" : "png.fight.rl";
			var leader:Leader = new Leader(isAttack, g.strength, skin, dir, attackEffect, next);
			leader.setDefenseValue(g);
			var ex:int = int((equipXml.equip.(@id == g.weaponID)[0]).@effect);
			leader.factorA =  fA + ex;
			arr.push(leader);
			//添加士兵
			for (var i:int = 0; i < n; i++)
			{
				if (inum > 0)
				{
					skin = dir == 0 ? "png.fight.wi" : "png.fight.ri";
					var infantry:Infantry = new Infantry(isAttack, m, skin, dir, attackEffect, next);
					infantry.factorA = fA;
					arr.push(infantry);
					inum--;
				}
				else if (bnum > 0)
				{
					skin = dir == 0 ? "png.fight.wa" : "png.fight.ra";
					var bowman:Bowman = new Bowman(isAttack, m, skin, dir, attackEffect, next);
					bowman.factorA = fA * 0.7;
					bowman.arrow = this.arrow;
					arr.push(bowman);
					bnum--;
				}
				else if (snum > 0)
				{
					skin = dir == 0 ? "png.fight.wk" : "png.fight.rk";
					var sowar:Sowar = new Sowar(isAttack, m, skin, dir, attackEffect, next);
					sowar.factorA = fA;
					arr.push(sowar);
					snum--;
				}
			}
			if (arr.length > 0)
			{
				var ba:BaseArmy = arr[arr.length - 1];
				ba.hp += d;
			}
			
			return arr;
		}
		
		private function getFactorA(g:GeneralVO):int
		{
			var x:XML = config.hurt.factorA.power.(@min <= g.power && g.power <= @max)[0];
			var a:int = int(x.@value) * g.power * 0.01 + (1 + Math.random() * 8);
			return a;
		}
		
		private function openControlPanel():void
		{
			Kyb.setOperater(controlPanel);
			controlPanel.visible = true;
			infoPanel.visible = false;
			send(FightC.SHOW_DEFENSE_HEAD,false);
		}
		
		private function openInfoPanel():void
		{
			Kyb.setOperater(infoPanel);
			controlPanel.visible = false;
			infoPanel.visible = true;
			send(FightC.SHOW_DEFENSE_HEAD,true);
			next();
		}
		
		private function next():void
		{
			if (controlPanel.visible || isFightOver)
				return;
				
			var ba:BaseArmy = allUnit[curUnitIndex];
			//移除已经死亡或逃跑的士兵
			while (ba.state == 4 || ba.state == 5)
			{
				allUnit.splice(curUnitIndex, 1);
				
				//if (ba is Leader)
					//return;
					
				ba = allUnit[curUnitIndex];
			}
			
			//骑士和武将有两轮执行动作的机会
			var sw:Sowar = ba as Sowar;
			if (sw)
			{
				if (sw.isSecondTimes)
				{
					sw.isSecondTimes = false;
					curUnitIndex++;
					if (curUnitIndex == allUnit.length)
						curUnitIndex = 0;
				}
				else
				{
					sw.isSecondTimes = true;
				}
			}
			else
			{
				curUnitIndex++;
				if (curUnitIndex == allUnit.length)
					curUnitIndex = 0;
			}
			
			var tl:BaseArmy = ba.isAttack ? defenseTeam[0]:attackTeam[0];
			ba.work(mapData,tl);
		}
		
		private function initMap(type:int):void
		{
			Lyr.map.addChild(this);
			map.bitmapData = App.asset.getBitmapData("png.fight.terrain_" + type);
		}
		
		private var map:Bitmap;
		/**地图数据,存储武将士兵及地形,null为可走*/
		private var mapData:Array;
		private var armyPanel:Sprite;
		private var config:XML;
		private var equipXml:XML;
		private var attackTeam:Array;
		private var defenseTeam:Array;
		private var allUnit:Array;
		private var curUnitIndex:int;
		private var controlPanel:ControlPanel;
		private var infoPanel:InfoPanel;
		private var infoAttackVO:InfoVO;
		private var infoDefenseVO:InfoVO;
		private var attackEffect:Bitmap;
		private var arrow:Clip;
		private var isFightOver:Boolean;
		static private const FORMATIONS:Array = [Cnt.FORMATION_1, Cnt.FORMATION_2, Cnt.FORMATION_3, Cnt.FORMATION_4];
	}

}